Fix 21051:bcc09eb7379f "x86_32: Relocate multiboot modules to below 1GB."
authorKeir Fraser <keir.fraser@citrix.com>
Wed, 24 Mar 2010 11:06:48 +0000 (11:06 +0000)
committerKeir Fraser <keir.fraser@citrix.com>
Wed, 24 Mar 2010 11:06:48 +0000 (11:06 +0000)
Copy the modules in ascending order in memory, rather than decsending
order. This reduces the likelihood of the second relocation (in
setup.c) corrupting modules through accidental overwriting.

Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
xen/arch/x86/boot/reloc.c

index 233a94f3474a7e27c411b8bb1e395fd2d972f9d2..47b558b29cd3d468d15c9d6319657c9ec5f0f40a 100644 (file)
@@ -68,29 +68,37 @@ multiboot_info_t *reloc(multiboot_info_t *mbi_old)
     {
         module_t *mods = reloc_mbi_struct(
             (module_t *)mbi->mods_addr, mbi->mods_count * sizeof(module_t));
+        u32 max_addr = 0;
+
         mbi->mods_addr = (u32)mods;
+
         for ( i = 0; i < mbi->mods_count; i++ )
         {
-#if XEN_BITSPERLONG == 32
-            /*
-             * 32-bit Xen only maps bottom 1GB of memory at boot time.
-             * Relocate modules which extend beyond this (GRUB2 in particular
-             * likes to place modules as high as possible below 4GB).
-             */
+            if ( mods[i].string )
+                mods[i].string = (u32)reloc_mbi_string((char *)mods[i].string);
+            if ( mods[i].mod_end > max_addr )
+                max_addr = mods[i].mod_end;
+        }
+
+        /*
+         * 32-bit Xen only maps bottom 1GB of memory at boot time. Relocate 
+         * modules which extend beyond this (GRUB2 in particular likes to 
+         * place modules as high as possible below 4GB).
+         */
 #define BOOTMAP_END (1ul<<30) /* 1GB */
-            static void *mod_alloc = (void *)BOOTMAP_END;
-            u32 mod_len = mods[i].mod_end - mods[i].mod_start;
-            if ( mods[i].mod_end > BOOTMAP_END )
+        if ( (XEN_BITSPERLONG == 32) && (max_addr > BOOTMAP_END) )
+        {
+            char *mod_alloc = (char *)BOOTMAP_END;
+            for ( i = 0; i < mbi->mods_count; i++ )
+                mod_alloc -= mods[i].mod_end - mods[i].mod_start;
+            for ( i = 0; i < mbi->mods_count; i++ )
             {
-                mod_alloc = (void *)
-                    (((unsigned long)mod_alloc - mod_len) & ~15ul);
+                u32 mod_len = mods[i].mod_end - mods[i].mod_start;
                 mods[i].mod_start = (u32)memcpy(
                     mod_alloc, (char *)mods[i].mod_start, mod_len);
                 mods[i].mod_end = mods[i].mod_start + mod_len;
+                mod_alloc += mod_len;
             }
-#endif
-            if ( mods[i].string )
-                mods[i].string = (u32)reloc_mbi_string((char *)mods[i].string);
         }
     }